/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package titanisu.templates.helperClasses;

import com.sun.script.javascript.RhinoScriptEngine;
import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.script.ScriptException;

/**
 *
 * @author Balaji
 */
public class MainHelper {

    public net.sourceforge.jeuclid.swing.JMathComponent getMMLAsComponent(String Filename) {

        net.sourceforge.jeuclid.swing.JMathComponent jm = new net.sourceforge.jeuclid.swing.JMathComponent();
        titanisu.commonUtil.fileUtil fu = new titanisu.commonUtil.fileUtil();
        String mmlData = fu.readFile(Filename);
        jm.setContent(mmlData);
        return jm;
    }

    public ArrayList getMMLTemplateFor(String type, int level) {
        String contents[] = new String[4];
        Random r = new Random();
        ArrayList templates = new ArrayList();
        /*
         * INDEXING EDTAILS  
         * 0 : question template
         * 1 : Solution Numerator Template
         * 2 : Solution Denomminator Template
         * 3 : solutions array, this is used only when there are multiple possible solutions
         * 4 : Optons array array consisting muliple options
         * 5 : Constraints for variables it's an array within the variable
 
         * IF LENGTH IS 2 THERE IS ONLY NUMERATOR AND OPTIONS ARE RANDOM NUMBERS
         * IF LENGTH IS 3 THERE IS NOMINATOR AND DENOMINATOR AND OTHER OPTIONS ARE RANDOM NUMBERS
         * 
         */
        if (type == "lesv" && level == 1) {
            int templatesCount = 4;

            int retTempl = r.nextInt(templatesCount);


            switch (retTempl) {
                case 0:

                    templates.add(0, "<math>        <mi>titns0titns</mi>         <mi>x</mi>         <mo>opPM0</mo>         <mi>titns1titns</mi>         <mo>=</mo>       <mi>titns2titns</mi>      </math>");
                    templates.add(1, "titns2titns  opPM0 (( -1 ) * titns1titns)");
                    templates.add(2, "titns0titns");

                    break;
                case 1:
                    templates.add(0, "<math>        <mfrac>       <mi>x</mi>  <mi>titns0titns</mi>    </mfrac>   <mo>opPM0</mo>         <mi>titns1titns</mi>         <mo>=</mo>       <mi>titns2titns</mi>      </math>");
                    templates.add(1, "(titns2titns  opPM0 (( -1 ) * titns1titns) )* titns0titns");
                    break;
                case 2:
                    templates.add(0, "<math>        <mfrac>       <mi>x</mi>  <mi>titns0titns</mi>    </mfrac>   <mo>opPM0</mo>        <mfrac>       <mi>x</mi>  <mi>titns1titns</mi>    </mfrac>          <mo>=</mo>       <mi>titns2titns</mi>      </math>");
                    templates.add(1, "titns0titns*titns1titns*titns2titns");
                    templates.add(2, "titns1titns opPM0 titns2titns");

                    break;
                case 3:

                    templates.add(0, "<math>        <mfrac>       <mi>titns0titns</mi>   <mi>x</mi>    </mfrac>   <mo>opPM0</mo>        <mfrac>       <mi>titns1titns</mi>  <mi>titns2titns</mi>    </mfrac>          <mo>=</mo>       <mi>titns3titns</mi>      </math>");
                    templates.add(1, "titns2titns*titns0titns");
                    templates.add(2, "titns2titns*titns3titns opPM0 titns1titns ");
                    break;
                default:
                    System.out.println("invalid template number in " + Class.class.getName());

            }

        }



        if (type == "qe" && level == 1) {

            /*
             * THIS IS A MULTI SOLUTIONS EXAMPLE  QUARDRATIC EQUATIONS, 2 SOLUTIONS
             */
            templates.add(0, "<math> <mi>titns0titns </mi> <msup> <mi>x</mi> <mi>2</mi> </msup> <mo> opPM0 </mo> <mi> titns1titns  </mi> <mi>x</mi> <mo> opPM1 </mo> <mi>titns2titns  </mi> <mo> = </mo> <mn>0</mn> </math>");
            ArrayList solutions = new ArrayList();

            solutions.add(0, " - titns1titns + Math.sqrt(Math.pow(titns1titns,2)-4*titns0titns * titns2titns )");
            solutions.add(1, "2*titns0titns");
            solutions.add(2, " - titns1titns - Math.sqrt(Math.pow(titns1titns,2)-4*titns0titns * titns2titns )");
            solutions.add(3, "2*titns0titns");
            templates.add(1, null);
            templates.add(2, null);

            templates.add(3, solutions);

            ArrayList constraints = new ArrayList();
            constraints.add(0, "titns0titns!=0");
            constraints.add(1, "Math.pow(titns1titns,2) >= 4*titns0titns*titns2titns");
            templates.add(4, null);
            templates.add(5, constraints);

        }





        return templates;
    }

    public ArrayList resolveTemplate(ArrayList template) {
        ArrayList resolved = new ArrayList();
        resolved = resolveNums(template);
        resolved = resolveOperators(resolved);
        System.out.println("------------- TEMPLAT RESOLVED ------------- ");

        for (int i = 1; i < resolved.size(); i++) {
            String tempi = (String) resolved.get(i);

            {
//                System.out.println("tempi = " + tempi);
                com.sun.script.javascript.RhinoScriptEngine se = new RhinoScriptEngine();
                try {
                    System.out.println("ev = " + tempi);

                    String ev = se.eval(tempi).toString();
                    ev = ev.substring(0, ev.length() - 2);
                    System.out.println("se.eval(tempi) = " + Integer.parseInt(ev));
                    resolved.set(i, ev);

                } catch (ScriptException ex) {
                    Logger.getLogger(MainHelper.class.getName()).log(Level.SEVERE, null, ex);
                }

            }

        }

        System.out.println("Values being printed");

        return resolved;
    }

    private ArrayList resolveNums(ArrayList template) {

        ArrayList resolved = new ArrayList();

        titanisu.mathUtil.NumberFetcher nf = new titanisu.mathUtil.NumberFetcher();
        int size = template.size();
        String quest = (String) template.get(0);
        int varCount = getVarCount(quest, "nums");
        int[] nums = nf.getNDiffnumbers(varCount, 30);

        for (int j = 0; j < template.size(); j++) {

            String tempType = "";
            if (template.get(j) != null) {
                tempType = template.get(j).getClass().getName();
            }

            if (tempType != "") {



                if (tempType == "java.lang.String") {

                    String tempi = (String) template.get(j);

                    for (int i = 0; i < varCount; i++) {
                        tempi = tempi.replaceAll("titns" + i + "titns", nums[i] + "");
                    }
                    //System.out.println("tempi = " + tempi);
                    resolved.add(j, tempi);
                } else if (tempType == "java.util.ArrayList") {

                    ArrayList constraints = new ArrayList();
                    ArrayList resConstraints = new ArrayList();
                     constraints = (ArrayList) template.get(j);
                    for (int k = 0; k < constraints.size(); k++) {

                        String tempi = (String) constraints.get(k);

                        for (int i = 0; i < varCount; i++) {
                            tempi = tempi.replaceAll("titns" + i + "titns", nums[i] + "");
                        }
//                        System.out.println("tempi = " + tempi);

                        resConstraints.add(k, tempi);
                    }
                    resolved.add(j, resConstraints);
                }
            } else {
                resolved.add(j, null);
            }
//            System.out.println("Numbers  resolved.get(j) = " + resolved.get(j));
        }
        
        System.out.println(" -------------------------- RESOLVED INSTANCE IS ----------------------------------");
        for (int i = 0; i < resolved.size(); i++) {
            System.out.println("resolved.get("+i+") = " + resolved.get(i));
            
        }
        
        System.out.println(" -------------------------- TEMPLATE AS OF NOW IS ----------------------------------");
        for (int i = 0; i < template.size(); i++) {
            System.out.println("template.get(i) = " + template.get(i));
            
        }
        System.out.println(" -------------------------- ----------------------------------");
        
        return resolved;
    }

    private ArrayList resolveOperators(ArrayList template) {


        ArrayList resolved = new ArrayList();

        titanisu.mathUtil.NumberFetcher nf = new titanisu.mathUtil.NumberFetcher();
        int size = template.size();
        String quest = (String) template.get(0);
        int varCount = getVarCount(quest, "operators");



        for (int j = 0; j < template.size(); j++) {

            String tempType = "";
            if (template.get(j) != null) {
                tempType = template.get(j).getClass().getName();
            }

            if (tempType == "java.lang.String") {


                String tempi = (String) template.get(j);
                for (int i = 0; i < varCount; i++) {

                    VariablesHelper vh = new VariablesHelper();
                    tempi = tempi.replaceAll("opPM" + i, vh.getOperator("opPM"));

                }
                resolved.add(j, tempi);
            }
            else
                if(tempType == "")
                {
                    resolved.add(j, null);
                }
            else
                    if(tempType == "java.util.ArrayList")
                    {
                        resolved.add(j, template.get(j));
                    }
            
//            System.out.println("operators resolved.get(j) = " + resolved.get(j));
        }

System.out.println("resolved.size() resolve OPS = " + resolved.size());
        return resolved;


    }

    private int getVarCount(String quest, String convert) {

        int varCount = -1;
        if (convert == "nums") {

            String[] vars = quest.split("titns(\\d)titns");
            varCount = vars.length - 1;
            for (int i = varCount - 1; i > 0; i--) {
                if (quest.matches("(.*)titns" + i + "titns(.*)")) {
                    break;
                }
                varCount--;
            }

        }
        if (convert == "operators") {

            String[] vars = quest.split("op(\\w{2})(\\d)");
            varCount = vars.length - 1;
            for (int i = varCount - 1; i > 0; i--) {
                if (quest.matches("(.*)op(\\w{2})" + i + "(.*)")) {
                    break;
                }
                varCount--;
            }

        }
        if (varCount == -1) {
            System.out.println(" FATAL : incorrect varcount ");
        }
        return varCount;

    }

    public ArrayList resolveTemplateWithConstratints(ArrayList template) {
        ArrayList resolved = new ArrayList();
        ArrayList constraints = new ArrayList();

        int templateSize = template.size();

        if (template.get(5) == null) {
            System.out.println(" The template given does not have any constraints, please concider using the method sithout template");
        } else {
            constraints = (ArrayList) template.get(5);
//            template.remove(5);
        }

        do {
            resolved = resolveNums(template);
            resolved = resolveOperators(resolved);
            System.out.println("resolved.size() is "+template.size());
        } while (!validateConstratints( (ArrayList) resolved.get(5)));
        
        if(resolved.get(3)!=null)
        resolved.set(3, evaluateSolutions((ArrayList) resolved.get(3)));
        else
        {
            resolved.set(1, evaluateString( (String) resolved.get(1)));
            resolved.set(2, evaluateString( (String) resolved.get(2)));
                    
        }
        
            
        //System.out.println("------------- TEMPLATE WITH CONSTRAINTS RESOLVED ------------- " +resolved.get(0).toString());
        
        
        
        System.out.println(" -------------------------- RESOLVED INSTANCE BEING RETURNED IS ----------------------------------");
        for (int i = 0; i < resolved.size(); i++) {
            System.out.println("resolved.get("+i+") = " + resolved.get(i));
            
        }
        

        return resolved;

    }

    private boolean validateConstratints(ArrayList constraints) {
        boolean validationResult = true;
        System.out.println("looping at solving constraints" + constraints.size());

        for (int i = 0; i < constraints.size(); i++) {
            String tempi = (String) constraints.get(i);
            {
//                System.out.println("tempi = " + tempi);
                com.sun.script.javascript.RhinoScriptEngine se = new RhinoScriptEngine();
                try {
                    System.out.println("tempi = " + tempi);

                    String ev = se.eval(tempi).toString();
                    System.out.println("ev = " + ev);

                    //ev = ev.substring(0, ev.length());
//                    System.out.println("se.eval(tempi) = " + Integer.parseInt(ev));

                    if (ev == "false") {
                        validationResult = false;
                    }

                } catch (ScriptException ex) {
                    Logger.getLogger(MainHelper.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        System.out.println(" validation result is "+validationResult);
        return validationResult;
    }

    private ArrayList evaluateSolutions(ArrayList solutions) {
        for (int i = 0; i < solutions.size(); i++) {
       
            
                        String tempi = (String) solutions.get(i);
            {
//                System.out.println("tempi = " + tempi);
                com.sun.script.javascript.RhinoScriptEngine se = new RhinoScriptEngine();
                try {
                    System.out.println("tempi = " + tempi);

                    String ev = se.eval(tempi).toString();
                    Double val = Double.parseDouble(ev);
            ev = ""+Math.rint(val);
ev = ev.substring(0, ev.length()-2);
                    //
//                    System.out.println("se.eval(tempi) = " + Integer.parseInt(ev));
solutions.set(i, ev);
                } catch (ScriptException ex) {
                    Logger.getLogger(MainHelper.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
       
            
            
        }
        return solutions;
        
    }

    private Object evaluateString(String string) {
        
        
        com.sun.script.javascript.RhinoScriptEngine se = new RhinoScriptEngine();
        
                    String ev;
        try {
            ev = se.eval(string).toString();
//            System.out.println("ev = " + ev);
            Double val = Double.parseDouble(ev);
            string = ""+Math.rint(val);
        } catch (ScriptException ex) {
            Logger.getLogger(MainHelper.class.getName()).log(Level.SEVERE, null, ex);
        }
                    

                    //ev = ev.substring(0, ev.length());
//                    System.out.println("se.eval(tempi) = " + Integer.parseInt(ev));
return string;
        
    }
}
